/***********************************************************************
 * Module:  Piece.java
 * Author:  nabil
 * Purpose: Defines the Class Piece
 ***********************************************************************/
package model.jeu_de_dame;
import model.util.Couleur;
import model.util.Direction;
import java.util.*;
import model.gestion_mouvement.IPiece;
import model.gestion_mouvement.MouvementCalculateurPion;
import vue.PieceVue;

/**
 * <b>Piece représente une piece quelconque du jeu de dame (pion ou dame). Cette classe est abstract.
 * </b>
  * <p>
 * Une case est caractérisé par les informations suivantes :
 * <ul>
 * <li>La couleur de la piece</li>
 * <li>La positionX de la piece dans le damier</li>
 * <li>La positionY de la piece dans le damier</li>
 * <li>Une référence vers le damier</li>
 * <li>Un booleen indiquant si la piece a manger une autre lors du dernier cout</li>
 * </ul>
 * </p>
 * @see Damier
 * @see Piece
 * @author nabil mansouri
 * @version 2.0
 */
public abstract class Piece extends Observable implements IPiece{
     /**
         * La couleur de la piece "blanc" ou "noir"
         * 
         * @see Case#Case(int, int, String, Damier) 
         * @see Case#getCouleur() 
         */
   protected Couleur couleur;
         /**
         * La position x de la case dans le damier
         * 
         * @see Case#Case(int, int, String, Damier) 
         * @see Case#getPositionX() 
         */
   protected  int positionX;
       /**
         * La position y de la case dans le damier
         * 
         * @see Case#Case(int, int, String, Damier) 
         * @see Case#getPositionY() 
         */
   protected  int positionY;
       /**
         * Un boolean indiquant si la piece a mangé lors du dernier coup
         * 
         * @see Piece#aManger()  
         */
   protected boolean aManger;
          /**
         * Le damier auquel la case appartient
         * 
         * @see Case#Case(int, int, String, Damier) 
         * @see Case#getDamier() 
         * @see Case#getMesVoisines() 
         */
   protected Damier monDamier;


          /**
         * Constructeur Piece.
         * <p>
         * Initialisation de la piece avec les coordonnées de la case x et y. Cette méthode affecte
         * la couleur à la case et une référence vers le Damier. Et sa couleur lui est passé en paramètre.
         * </p>
         * @param monDamier 
         *           la référence vers le damier auquel elle appartient
         *@param  x
         *           la position x de la piece 
         *@param  y
         *           la position y de la piece 
         *@param  couleur
         *           la couleur de la piece 
         *  
         */
   protected Direction destination;
   protected boolean selected;
   public Piece(Damier monDamier, int x, int y,Couleur couleur)
   {
       this.monDamier = monDamier;
       this.couleur = couleur;
       this.positionX = x;
       this.positionY = y;
       
       aManger = false;
       
   }
   

    public void setDirection(Direction d)
   {
       this.destination = d;
   }
    /**Retourne vrai si la piece a manger lors du dernier déplacement
     * @return true si elle a manger false sinon
     */
   public boolean aManger()
   {
       return aManger;
   }
   
   /**Retourne la couleur de la piece
     * @return "blanc" si la piece est blanche "noir" sinon
     */
    public Couleur getCouleur() {
        return couleur;
    }
    
      /**Retourne le damier auquel appartient la piece
     * @return le damier
     */
    public Damier getDamier()
    {
     return this.monDamier;   
    }    
    
  /**Retourne la case sur laquelle est la piece. Pour celà elle va interroger le damier.
    * @return La case si elle existe null sinon
     */
    public Case getCase()
    {
        try {
            return this.monDamier.getCase(positionX, positionY);
        } catch (Exception ex) {
           return null;
        }
    }
  /**Retourne true si la piece passer en paramètre a la même couleur false sinon
     * @param p
     *         La piece pour laquelle on doit dire si elle est amie ou ennemie
    * @return true si la piece passer en paramètre a la même couleur false sinon
     */
    public boolean isAmie(Piece p)
    {
        return this.couleur==p.getCouleur();
    }
    
      /**Retourne true si la piece passer en paramètre est de couleur differente false sinon
     * @param p
     *         La piece pour laquelle on doit dire si elle est ennemie ou non
    * @return true si la piece passer en paramètre est de couleur differente false sinon
     */
    public boolean isEnnemie(Piece p)
    {
        return this.couleur!=p.getCouleur();
    }
    
    /**Retourne la liste des cases que la piece peut atteindre. Cette methode est abstraite.
     */
    public abstract ArrayList<Case> getCasesAccessibles();
    
   /**Retourne true si la piece a été déplacé vers la case arrive. Cette methode est abstraite.
     */
    public abstract boolean seDeplacer(Case arrive);
    
   /**
     * retourne true si la piece passé en paramètre a été manger. La piece manger est supprimé du damier.
     * @param p
     *          La piece a manger
     * @return true si la piece passé en paramètre a été manger false sinon.
     * 
     */
    public boolean manger(Piece p)
    {
       if(this.monDamier.supprimerPiece(p))
        {
            this.aManger = true;
            return true;
        }
        return false;
    }
    
       /**
     * @return the positionX
     */
     public int getPositionX() {
        return positionX;
    }

    /**
     * @param positionX the positionX to set
     */
    public void setPositionX(int positionX) {
        this.positionX = positionX;
        setChanged();
        notifyObservers(this.positionX);
    }

    /**
     * @return the positionY
     */
    public int getPositionY() {
        return positionY;
    }

    /**
     * @param positionY the positionY to set
     */
    public void setPositionY(int positionY) {
        this.positionY = positionY;        
        setChanged();
        notifyObservers(this.positionY);
        
    }
    
   /**
     * Deplace la piece de sa case actuelle vers la case arrive.
     * @param arrive
     *          La case destination
     */
    protected void effectuerDeplacement(Case arrive)
    {
        this.monDamier.affecterPiece(arrive, this);
    }
        
           /**
     * Retourne si la piece peut actuellement manger une autre. Cette méthode est abstract.

     * @return true si la piece peut manger false sinon
     * @see Case#getMesVoisines() 
     */
    public abstract boolean peutManger();

  
    public abstract boolean peutBouger();
    
    
    public void setSelected(boolean selected) {
        this.selected = selected;
        this.setChanged();
        this.notifyObservers();
    }

    public boolean isSelected() {
        return selected;
    }
     public boolean isEnnemie(IPiece p) {
        return p.getCouleur()==this.getCouleur();
    }
    public abstract ArrayList<Case> getCheminOffensif();
    public abstract ArrayList<Case> getPlusSurChemins();
    
}